/*
 * 
 */
#include <iostream>
#include <cstring>
#include <boost/cstdint.hpp>
#include "ui.h"
#include "workerdiscovery.h"
#include "workerdescriptor.h"
#include "manager.h"

using namespace std;

namespace CORE
{
    void discoveryBehaviour(boost::uint16_t port)
    {
        cout << "Initializing discovery node . . ." << endl;

        WorkerDiscovery wd;

        if (port != 0)
            wd.setPort(port);

        wd.addWorker(WorkerDescriptor("localhost", 14000));
        wd.addWorker(WorkerDescriptor("localhost", 14001));
        wd.addWorker(WorkerDescriptor("localhost", 14002));
        wd.addWorker(WorkerDescriptor("localhost", 14003));
        wd.addWorker(WorkerDescriptor("localhost", 14004));

        wd.run();
    }

    void managerBehaviour(boost::uint16_t port, boost::uint16_t port2)
    {
        cout << "I'm a manager node! Initializing . . ." << endl;

        Manager m;

        if (port != 0)
            m.setPort(port);

        if  (port2 != 0)
            m.setDiscoveryAddress("localhost", port2);

        m.run();

    }

    void userInterfaceBehaviour(boost::uint16_t port, boost::uint16_t port2)
    {
        cout << "I'm an User Interface node! Initializing . . ." << endl;

        UI ui;

        if (port != 0)
            ui.setServerPort(port);

        if  (port2 != 0)
            ui.setManagerAddress("localhost", port2);

        ui.run();
    }

    void workerBehaviour(boost::uint16_t port, boost::uint16_t port2)
    {
        cout << "I'm a worker node! Initializing . . ." << endl;

        Worker w;

        // Init worker
        w.run();
    }

}

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        cout << "\nUsage: " << argv[0] <<" <type> [port] [port2]\n" << endl;

        cout << "Type: 0 UI, 1 Manager, 2 Discovery, 3 Worker\n" << endl;

        cout << "Default ports are:\n"
             << "- 11000 (UI)\n"
             << "- 12000 (Manager)\n"
             << "- 13000 (Discovery)\n"
             << "- 14000 (Worker)\n" << endl;

        cout << "port2 has a different meaning for each node:\n"
             << "- UI Node: manager node's port\n"
             << "- Manager Node: discovery node's port\n"
             << "- Discovery Node: unused currently\n"
             << "- Worker Node: UI node's port\n" << endl;

        return 1;
    }

    int type = atoi(argv[1]);

    boost::uint16_t port, port2;

    if (argc > 2)
        port = atoi(argv[2]);
    else
        port = 0;

    if (argc > 3)
        port2 = atoi(argv[3]);
    else
        port2 = 0;

    if (type == 0)
        CORE::userInterfaceBehaviour(port, port2);

    else if (type == 1)
        CORE::managerBehaviour(port, port2);

    else if (type == 2)
        CORE::discoveryBehaviour(port);

    else if (type == 3)
        CORE::workerBehaviour(port, port2);

    return 0;
}
